• book article 文章
  • book article sum
  • 文章表、文章信息索引
  • 更新
  • 文章操作
  • 应用内操作
  • head version -- 当前 git head 版本
  • CURD create update rename delete
  • 编辑
  • 自动保存
  • 手动保存
  • 手动tag
  • 图片上传
  • 图片转储
  • 图片缓存
  • 历史版本查看
  • 操作菜单
  • 应用外操作
  • 外部修改更新 repo update,gogs webhook
  • webhooks 排错记录
  • webhook 创建
  • repo sync
  • git文章管理
  • 文件格式一:markdown
  • 加锁
  • 编辑
  • 文件格式二:zrtf html;客户端
  • 文章查看 & 目录结构
  • 默认 readme
  • 中文路径
  • 用户文章浏览
  • 使用iframe的原因
  • 链接跳转
  • 上一篇 下一篇
  • 浏览方式
  • 点击标题自动切换url 修改url
  • 大纲自动折叠、定位,并且带高亮
  • 查看选定文章
  • 路径排序
  • 文章可见性
  • 文章访问历史记录
  • 评论
  • es 搜索 api
  • 点击查看大图
  • book article 文章

    book article sum

    mynote核心。
    目前支持两种格式:
    1 文件格式二:zrtf html;客户端 格式
    2 文件格式一:markdown 格式,此格式支持在页面上编辑。
    lv1=mynote lv2= type=todo
    book页面需要展示的元素:
     1 作者、头像
     2 创建时间、更新时间
     3 上一篇、下一篇(同时显示标题)
    现在是每次读取所有的文章,动态计算next、previous
    lv1= lv2= type=

    文章表、文章信息索引

    除了在git中存储了文章的完整信息,还在数据库中维护了一张文章的索引表(article),包含以下信息:
    lv1=mynote lv2= type=todo
    获取文章内容时,需要传入version,与当前version不一致时,需要动态的从git中获取。git show
    lv1=mynote lv2= type=todo
    article 表新增title字段,E:\uninote\mynote\basic\models\api\Userinfo.php all_recommend 等地方不再返回 article_id
    article_id 规范为path
    item规范为aid

    更新

    lv1=mynote lv2= type=todo
    1 用户在应用内操作时,同时更新索引
    lv1=mynote lv2= type=todo
    git server 交互放timer中?
    lv1=mynote lv2= type=todo
    数据库和文件系统一致性检查
    不一致怎么处理?

    文章操作

    应用内操作

    指使用包括网站、app、小程序等一切mynote提供的应用进行的操作。
    目前,在页面上仅支持markdown格式的操作,其他格式的文件,请在外部操作:
    支持的操作:新建、save、rename、mv、del、新建文件夹等;
    所有的操作都放在锁中_git_op_lock
    lv1=mynote lv2= type=todo
    冲突的报错不明确,以及所有的errno
    lv1=mynote lv2= type=todo
    前端翻译错误代码
    lv1= lv2= type=

    head version -- 当前 git head 版本

    repo op fix & optimization 
    opt: 缓存 HEAD version,避免不必要的分支切换、合并等(直接在 master 上修改)
    verson 改为 redis 缓存
    version 存数据库中?push 前更新到数据库中即可 -- 暂无必要
    $this->_shell_ex(['git log -1 --pretty=%h']);
    lv1= lv2= type=

    CURD create update rename delete

    update: version不需要最新,但需要传 path(不知道在某个 version 状态下 aid 对应的 path 是什么)
    create/rename/del: version 需要最新,不用传,不需要传 path(create除外)
    SHA-1: 32aed71df0e17b6f6507bcddebdeceb60a609639
    * fix: CURD version & path 问题
    SHA-1: 7e08119afc29b6a394620e0ba1b04a48f7cae0c8
    * change: create 时不传 version
    SHA-1: 293996e19e2736df73d855258d98b194e6b77d91
    * change: rename/del 时不传 version
    lv1= lv2= type=

    编辑

    lv1=mynote lv2= type=todo
    异步保存,不要卡死
    避免多个请求乱序返回:返回值还需要带上old version,和当前version比较,相同才更新,不同不更新。??
    一个version还需要带上minor version,从1开始计数。以version#min_version表示。
    比如第一次保存时,传参为123a#1,第二次则为123a#2,依次类推。当server保存了#2时,则不应该保存之前的版本。
    保存成功返回给前端,更新version。minor version重置。
    每次加载编辑页面时,后台分配一个唯一id,在save时保存此id对应的version#min_version。如果version匹配,则校验min。每十分钟清理一次,超过10分钟的。
    or 用redis ttl来解决
    lv1=mynote lv2= type=todo
    当前文章没有修改时,disable保存按钮
    如何判断没有修改?记录下原始的内容?
    enable条件:有修改&上次保存已经完成
    所有内容原样保存,eg:
    %<>.,+=_-/*\[]{}~!@#$%^&()
    保存时检测到服务器端有更新,提示:是否合并并刷新?注意刷新后之前的修改无法撤销(ctrl+z失效)

    自动保存

    TODO
    自动保存冲突时:警告冲突
    通过客户端拉取并解决冲突。

    手动保存

    ctrl + s,按钮

    手动tag

    TODO 手动指定tag,用户可以只查看tag,非tag可能会被清理以节省空间

    图片上传

    图片存储,改为 md5 两级 dir 
    选择图片
    剪贴板:ctrl c(从浏览器、微信、word等)、截图、本地文件

    图片转储

    将外部图片保存为内部(本域名)图片
    采用绝对路径(截图、上传图片、粘贴)
    粘贴时触发 >> 用户主动触发
    图片转储可选,默认不开启? 
    lv1= lv2= type=

    图片缓存

    不转储,但将所有的图片缓存起来
    前端通过xhr的方式加载,如果原始地址加载失败,则使用 fallback to 缓存

    历史版本查看

    TODO
    lv1= lv2= type=todo

    操作菜单

    hover时显示toolbar
    lv1= lv2= type=
    复制链接、新窗口中打开链接
    这个非当前用户都可以看到

    应用外操作

    指任何mynote以外第三方提供的操作方式。完成后再通过git上传到服务器。见git文章管理 
    lv1= lv2= type=

    外部修改更新 repo update,gogs webhook

    public static $OP_UPDATE = 'UPDATE'; // 拉取并更新 $uid 指定用户的仓库
    与内部修改共用大部分代码
    在docker环境中,这样配置有问题:http://192.168.0.40/api/markdown/repo-update,无法路由出docker,再回到docker?需要改为 http://127.0.0.1/api/markdown/repo-update,同时需要修改 nginx 的 nuxt.conf 配置,避免被重定向:
    server_name __front_host 127.0.0.1;
    webhooks + 手动触发
    http://127.0.0.1/api/markdown/repo-update gogs 重启后ok
    http://192.168.0.43:180/api/markdown/repo-update 这个报找不到 route?(推送测试处查看)
    需要将数据库改为 utf8 编码;否则这里看不到推送记录:
    lv1=mynote lv2= type=

    webhooks 排错记录

    nginx proxy_pass 反向代理 
    http post programming sum 
    http dump 
    配置了 ip 重定向到域名,导致通过 ip 访问时重定向了, post就变成了get请求。
    解决:直接访问接口,不要走 nginx>nuxt>接口 的流程
    经验:严格配置 server name(先将无关的conf移除):
    nginx: [warn] conflicting server name "" on 0.0.0.0:80, ignored

    webhook 创建

    SHA-1: e42169b58474debc740dfb08b8fd8a5db3023111
    * feat: 用户注册时创建 webhook
    https://github.com/gogs/docs-api/blob/master/Repositories/Webhooks.md#create-a-hook
    lv1= lv2= type=

    repo sync

    public static $OP_SYNC = 'SYNC'; // 同步数据库/es与文件系统
    完成后重新统计指定用户的文章数
    尽量保证文章 id 不变化
    lv1=mynote lv2= type=

    git文章管理

    无论用户是在内、外部操作,最终都是通过git来存储的。如果存在并发修改,也是通过git来自动合并的。
    如需应用外管理,参见git remote url & git ssh key 
    lv1= lv2= type=

    文件格式一:markdown

    toc、标题集成
    lv1=mynote lv2= type=todo
    没有变化要尝试合并
    lv1=mynote lv2= type=todo
    安全:
    禁止rename 可以任意移动文件
    禁用docs下的php文件执行
    给docs目录增加白名单,只有白名单中的文件类型允许访问
    彻底禁用用户脚本?
    lv1=mynote lv2= type=todo
    del:
    E:\uninote\mynote\basic\web\link\take\lib\graphics
    Md.php  提取到class level var:
    {$_SESSION['user_info']['username']}
    lv1=mynote lv2= type=todo
    markdown也需要唯一id(分析得出,但可能丢失)
    lv1= lv2= type=

    加锁

    所有操作都需要加锁
    lv1=mynote lv2= type=todo
    所有操作都需要带version,并在服务器上进行合并
    编辑-rename测试
    通过php file 加锁、加锁
    fopen($path, "x");
    fopen 什么时候异常?在linux服务器上,如果文件存在抛出异常,但其他平台,直接输出警告。
    function create_file_lock($path, &$output = null)
    function release_file_lock($f, $path)

    编辑

    关闭时需要确认保存
    lv1=mynote lv2= type=todo
     全屏加快捷键
    lv1=mynote lv2= type=todo
    添加保存并退出功能(发布),跳转到当前编辑页面,进行查看
    lv1= lv2= type=

    文件格式二:zrtf html;客户端

    lv1= lv2= type=todo
    fh client文章间跳转问题
    windows server,fh html生成
    SHA-1: 1c8a63e21a32abb41dede9911f347f8ed1a98e85
    * mynote client <a>标签处理:查询href引用路径,如果在数据库中,则转为id形式
    lv1= lv2= type=

    文章查看 & 目录结构

    SHA-1: dcb27f36d27dd01162395fa59ebb8f4d026c3354
    * 使用phpQuery对资源进行处理:img、css转为的绝对路径;移除script
    使用phpQuery处理为绝对路径
    util.js中动态加载pi.js等,这个现在无法处理,因此彻底禁用(移除)了js,只保留了大纲的json数据。
    tree.js
    /**
     * 导航信息的全局变量
     */
    var main_src;
    var iframe_src;
    var cur_aid = null; // 当前浏览的article id
    var outline_num;  // 当前浏览的大纲
    lv1= lv2= type=

    默认 readme

    不区分大小写
    refresh + route 两种加载方式
    路由逻辑:从 author/ 进入某个作者,会跳转(路由替换)到 readme(如果有,没有则空白页);再回退一次,进入 author 页
    http://localhost:3000/book/1054715476
    query + hash 也能正确跳转
    http://localhost:3000/book/1099245323?a=b
    * [opt]: 利用 router 相关 API 重新实现默认打开 README
    SHA-1: 71377076f0731b16a9408221b342f5e969b75d00
    lv1= lv2= type=

    中文路径

    使用git在服务器上会自动转为utf8编码,直接使用工具上传,会保持原始的编码。
    apache url编码 似乎windows下没有解决方案

    用户文章浏览

    lv1= lv2= type=

    使用iframe的原因

    必须用iframe,不然相对路径无法控制
    无法回退
    css相互影响(content影响framework)
    无法open in new tab
    用户选择某一篇文章时,主frame的url也跟着改变,这样刷新时能知道上次浏览的iframe地址。iframe也跟着load
    刷新后,目录结构、文章标题都会定位到上次浏览位置;同时图标也会变化
    lv1= lv2= type=todo

    链接跳转

    文章链接:如果是链接当本作者,则页面跳转;如果是其他作者或者站外链接,则新窗口打开。
    两种链接,以不同颜色显示(区分样式)。

    上一篇 下一篇

    同上,也要本页面打开
    上一篇、下一篇的链接形式,要从 
    lv1= lv2= type=todo

    浏览方式

    排序,默认tree,还可以时间排序。。
    lv1= lv2= type=todo

    点击标题自动切换url 修改url

    这样方便复制给别人。
    https://demo.fastadmin.net/docs/command#%E4%B8%80%E9%94%AE%E7%94%9F%E6%88%90%E8%8F%9C%E5%8D%95-2
    利用JS实现前端路由 
    http://doc.scrapy.org/en/latest/intro/overview.html#what-s-next
    链接图标放前面
    https://github.com/coolwanglu/pdf2htmlEX

    大纲自动折叠、定位,并且带高亮

    参考掘金
    lv1= lv2= type=

    查看选定文章

    1、要保证在加载的过程中,可读。随着文章加载的内容增加,要调整文章高度
    2、加载完成后需要滚动到顶部。TODO:这里是onload滚动还是documentReady时滚动??目前,还没法保证绝对滚动到top,cyb/help这篇文章就不行
         如果带小标题锚点,则不要滚动
    这里面涉及到太多异步的问题(加断点调试和正常运行看到的结果不一样)
    lv1= lv2= type=todo
    鼠标hover图片上时改为放大镜,并显示图片边框。

    路径排序

    同windows排序结果
    lv1= lv2= type=todo

    文章可见性

    public、private、private-local(不上传到server)
    分组:支持不同的组,有不同的可见性
    lv1= lv2= type=

    文章访问历史记录

    nginx variables test 
    proxy_set_header x-real-ip $remote_addr;
    SHA-1: 1b6f409e81e70eda6f1f4d2dee84b9245af90f86
    * feat: 记录访问历史
    ip统计
    lv1= lv2= type=
    ip反解区域
    referer统计
    ua

    评论

    点击头像到作者首页 
    lv1= lv2= type=

    es 搜索 api

    mynote es elasticsearch 
    搜索 
    /api/search/index 搜索全部类型接口
    /api/search/search 搜索指定类型接口
    lv1= lv2= type=

    点击查看大图

    node = event.target;node.naturalWidth > node.clientWidth
    md = $$("#markdown-preview")[0]
    // md.innerHTML = "a";
    // md.innerHTML = "http://docs.dajxyl.com, http://docs.dajxyl.com"
    md.innerHTML = md.innerHTML.replace(/http:\/\/docs.dajxyl.com/g, "https://docs.dajxyl.com")
    if (imageWidth > currentWidth) {
      node.style.cursor = "pointer";
    click 改变样式改为提前就全部计算一遍